package megadrum.gui;

import megadrum.*;

import javax.sound.midi.*;
import javax.swing.JProgressBar;
import javax.swing.JSpinner;
import java.awt.GridLayout;
import java.awt.Color;
import javax.swing.JTextField;

public class MidiLog extends javax.swing.JDialog implements Receiver {

    public MidiLog(MegadrumConfigTool mct) {
        super(mct, "Pad hits: velocity log", false);
        initComponents();
        initComponents2();

        //repack the GUI because the bar panel maybe bigger or smaller than default size
        pack();
    }

    private void initComponents2(){
        padColor = new Color(51, 153, 255);
        chokeColor = new Color(255, 153, 0);
        xtalkColor = new Color(200, 20, 20);
        note.setModel(new CustomSpinnerNoteModel(1, 1, 127, 1));
        new PopupSlider(note);
        timePanel.setLayout(new GridLayout(0, Common.NUMBER_OF_MIDILOG_ENTRIES, 2, 0));
        barPanel.setLayout(new GridLayout(0, Common.NUMBER_OF_MIDILOG_ENTRIES, 2, 0));
        notePanel.setLayout(new GridLayout(0, Common.NUMBER_OF_MIDILOG_ENTRIES, 2, 0));
        bar = new JProgressBar[Common.NUMBER_OF_MIDILOG_ENTRIES];
        timeLabel = new JTextField[Common.NUMBER_OF_MIDILOG_ENTRIES];
        noteLabel = new JTextField[Common.NUMBER_OF_MIDILOG_ENTRIES];
        for (int i = 0; i < Common.NUMBER_OF_MIDILOG_ENTRIES; i++) {
            bar[i] = new JProgressBar(1, 0, 127);
            //bar[i].setBackground(Color.WHITE);
            bar[i].setForeground(padColor);
            bar[i].setStringPainted(true);
            bar[i].setString("0");
            bar[i].setFocusable(false);
            timeLabel[i] = new JTextField("0");
            timeLabel[i].setBackground(java.awt.Color.WHITE);
            timeLabel[i].setFont(new java.awt.Font("Tahoma", 0, 9));
            timeLabel[i].setColumns(2); //2 columns are enough to fit the longest possible text ("127")
            timeLabel[i].setEditable(false);
            timeLabel[i].setFocusable(false);
            noteLabel[i] = new JTextField("0");
            noteLabel[i].setBackground(java.awt.Color.WHITE);
            noteLabel[i].setFont(new java.awt.Font("Tahoma", 0, 9));
            noteLabel[i].setColumns(2); //2 columns are enough to fit the longest possible text ("127")
            noteLabel[i].setEditable(false);
            noteLabel[i].setFocusable(false);
            barPanel.add(bar[i]);
            timePanel.add(timeLabel[i]);
            notePanel.add(noteLabel[i]);
        }
        ((JSpinner.DefaultEditor) note.getEditor()).getTextField().setBackground(java.awt.Color.WHITE);
        ((JSpinner.DefaultEditor) note.getEditor()).getTextField().setForeground(java.awt.Color.BLACK);

    }

    public void insertEvent(int noteValue, int velocity) {
        if (!viewOnly.isSelected() || ((CustomSpinnerNoteModel)note.getModel()).getIntValue() == noteValue) {
            for (int i = 0; i < bar.length - 1; i++) {
                bar[i].setValue(bar[i + 1].getValue());
                bar[i].setString(bar[i + 1].getString());
                bar[i].setForeground(bar[i + 1].getForeground());
                timeLabel[i].setText("" + timeLabel[i + 1].getText());
                noteLabel[i].setText("" + noteLabel[i + 1].getText());
            }
            if (velocity == Common.CHOKE) {
                bar[bar.length - 1].setValue(127);
                bar[bar.length - 1].setString("CHOKE");
                bar[bar.length - 1].setForeground(chokeColor);
            } else if(detectXtalk.isSelected() && ((CustomSpinnerNoteModel)note.getModel()).getIntValue() != noteValue) {
                bar[bar.length - 1].setValue(velocity);
                bar[bar.length - 1].setString("" + velocity);
                bar[bar.length - 1].setForeground(xtalkColor);
            } else {
                bar[bar.length - 1].setValue(velocity);
                bar[bar.length - 1].setString("" + velocity);
                bar[bar.length - 1].setForeground(new Color(2 * noteValue, 153, 255));
            }
            long now = System.currentTimeMillis();
            long gap = now - lastTime;
            lastTime = now;
            timeLabel[timeLabel.length - 1].setText("" + (gap>1000?">1s":gap));
            noteLabel[noteLabel.length - 1].setText("" + noteValue);
        }
    }

    public void send(MidiMessage event, long time) {
        if (event instanceof ShortMessage) {
            //we only monitor noteOn and aftertouch events
            switch (event.getStatus() & 0xf0) {
                case 0x90:
                    if (((ShortMessage) event).getData2() != 0) {
                        insertEvent(((ShortMessage) event).getData1(), ((ShortMessage) event).getData2());
                    }
                    break;
                case 0xa0:
                    if (((ShortMessage) event).getData2() != 0) {
                        insertEvent(((ShortMessage) event).getData1(), Common.CHOKE);
                    }
                    break;
            }
        }
    }

    public void close() {
    }

    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        barPanel = new javax.swing.JPanel();
        notePanel = new javax.swing.JPanel();
        viewOnly = new javax.swing.JCheckBox();
        note = new javax.swing.JSpinner();
        timePanel = new javax.swing.JPanel();
        detectXtalk = new javax.swing.JCheckBox();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();

        org.jdesktop.layout.GroupLayout barPanelLayout = new org.jdesktop.layout.GroupLayout(barPanel);
        barPanel.setLayout(barPanelLayout);
        barPanelLayout.setHorizontalGroup(
            barPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 269, Short.MAX_VALUE)
        );
        barPanelLayout.setVerticalGroup(
            barPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 174, Short.MAX_VALUE)
        );

        org.jdesktop.layout.GroupLayout notePanelLayout = new org.jdesktop.layout.GroupLayout(notePanel);
        notePanel.setLayout(notePanelLayout);
        notePanelLayout.setHorizontalGroup(
            notePanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 269, Short.MAX_VALUE)
        );
        notePanelLayout.setVerticalGroup(
            notePanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 17, Short.MAX_VALUE)
        );

        viewOnly.setText("Monitor only this note:");
        viewOnly.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                viewOnlyStateChanged(evt);
            }
        });

        note.setEnabled(false);

        org.jdesktop.layout.GroupLayout timePanelLayout = new org.jdesktop.layout.GroupLayout(timePanel);
        timePanel.setLayout(timePanelLayout);
        timePanelLayout.setHorizontalGroup(
            timePanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 269, Short.MAX_VALUE)
        );
        timePanelLayout.setVerticalGroup(
            timePanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 17, Short.MAX_VALUE)
        );

        detectXtalk.setText("Detect Xtalk:");
        detectXtalk.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                detectXtalkStateChanged(evt);
            }
        });

        jLabel1.setText("Time gap (in milliseconds):");

        jLabel2.setText("Velocity (blue=note, orange=choke, red=xtalk):");

        jLabel3.setText("Midi Note number:");

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(layout.createSequentialGroup()
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(detectXtalk)
                            .add(viewOnly))
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(note, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 138, Short.MAX_VALUE))
                    .add(jLabel1)
                    .add(timePanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .add(jLabel2)
                    .add(barPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .add(jLabel3)
                    .add(notePanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .add(jLabel1)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(timePanel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jLabel2)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(barPanel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jLabel3)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(notePanel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 6, Short.MAX_VALUE)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                    .add(layout.createSequentialGroup()
                        .add(viewOnly)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(detectXtalk))
                    .add(note, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

private void viewOnlyStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_viewOnlyStateChanged
    if (viewOnly.isSelected()) {
        detectXtalk.setSelected(false);
        note.setEnabled(true);
        note.setToolTipText("Only this note's events will be shown");
    } else {
        note.setToolTipText("");
        note.setEnabled(false);
    }
}//GEN-LAST:event_viewOnlyStateChanged

private void detectXtalkStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_detectXtalkStateChanged
    if (detectXtalk.isSelected()) {
        viewOnly.setSelected(false);
        note.setEnabled(true);
        note.setToolTipText("Notes different from this one are considered Xtalk");
    } else {
        note.setToolTipText("");
        note.setEnabled(false);
    }
}//GEN-LAST:event_detectXtalkStateChanged

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel barPanel;
    private javax.swing.JCheckBox detectXtalk;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JSpinner note;
    private javax.swing.JPanel notePanel;
    private javax.swing.JPanel timePanel;
    private javax.swing.JCheckBox viewOnly;
    // End of variables declaration//GEN-END:variables
    private JProgressBar[] bar;
    private JTextField[] timeLabel;
    private JTextField[] noteLabel;
    private Color padColor,  chokeColor,  xtalkColor;
    private long lastTime = 0;
}
